package resources;


import it.sauronsoftware.base64.Base64;

import java.io.*;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.*;

import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;

import org.apache.log4j.Logger;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;

import utilities.Costanti;

import connectors.DBManager;
import connectors.VerbaliManager;
import entities.Notifica;



/*
 * Risorsa REST per la gestione delle Notifiche
 * occorre fare un POST HTPP all'indirizzo http://91.226.109.144/GestioneMulteServer/notifica/aggiungi
 * per aggiungere una nuova notifica di Multa nel DB
 * occorre fare un POST HTPP all'indirizzo http://91.226.109.144/GestioneMulteServer/notifica/cancella
 * per cancellare una notifica di Multa già inserita nel DB che non abbia gia' associato un verbale
 */

@Path("/notifica")
public class NotificaResource{
	
	static Logger logger = Logger.getLogger(NotificaResource.class);
	
	
	private Notifica creaOggettoNotifica(JSONObject datiRicevuti,String numeroVerbale) throws Exception{
		//CREAZIONE DELL'OGGETTO NOTIFICA a partire dal JSONObject ricevuto
		Notifica notifica = new Notifica( datiRicevuti.getString("data_ora"),
										  datiRicevuti.getString("via_comune"),
										  datiRicevuti.getDouble("sanzione"),
										  numeroVerbale,
										  datiRicevuti.getString("targa"));
		//set campo foto
		String foto_encoded = datiRicevuti.getString("foto");
		if(foto_encoded != null && !foto_encoded.equals("")){
			logger.info("Richiesta di aggiungi Notifica ricevuta con numero verbale "+numeroVerbale
					+" con foto");
			InputStream inputStream = new ByteArrayInputStream(foto_encoded.getBytes("UTF-8"));
			ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
			Base64.decode(inputStream, outputStream);
			notifica.setFoto(outputStream);
			outputStream.close();
			inputStream.close();
		}
		else{
			logger.info("Richiesta di aggiungi Notifica ricevuta con numero verbale "+numeroVerbale
					+" senza foto");
		}
		//set campo infrazioni
		ArrayList<Integer> infrazioni = new ArrayList<Integer>();
		JSONArray inf = datiRicevuti.getJSONArray("infrazioni");
		if(inf!=null){
			for(int i=0; i<inf.length();i++){
				infrazioni.add(inf.getInt(i));
			}
			notifica.setInfrazioni(infrazioni);
		}
		//set campo descrizioneInfrazioni
		ArrayList<String> descrizioneInfrazioni = new ArrayList<String>();
		JSONArray descInf = datiRicevuti.getJSONArray("descrizioneInfrazioni");
		if(descInf!=null){
			for(int i=0; i<descInf.length();i++){
				descrizioneInfrazioni.add(descInf.getString(i));
			}
			notifica.setDescrizioneInfrazione(descrizioneInfrazioni);
		}
		notifica.setLat(datiRicevuti.getDouble("lat"));
		notifica.setLongi(datiRicevuti.getDouble("longi"));
		return notifica;
		
	}
		
	@POST   @Path("/aggiungi")
	@Produces(MediaType.APPLICATION_JSON)
	@Consumes(MediaType.APPLICATION_JSON)
	public JSONObject nuovaNotifica(JSONObject datiRicevuti){
		 //
		 //codice per il calcolo tempo esecuzione
		 //			
		long inizio = System.currentTimeMillis();
		long fine = 0;
		long inizioDB = 0;
		long fineDB = 0;
		///////
		JSONObject jsonToReturn = new JSONObject();
      	boolean errore = false;
      	DBManager dBmanager = null;
      	Connection con = null;
      	Notifica notifica = null;
		String numeroVerbale = "";	
      	String esito = ""; 
      	String matricola = "";
		String codice_agente = "";
		String imei = "";
      	
      	//inizializzo i campi dell'oggetto JSON di risposta
      	try{
			jsonToReturn.put("esito_operazione", HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
			jsonToReturn.put("codice_errore","");
			jsonToReturn.put("info","");
			jsonToReturn.put("numero_verbale", "");
			jsonToReturn.put("tsFE",-1);
			jsonToReturn.put("tsBE",-1);
      		
      	}catch(JSONException je){}
      	
	    //parsing dei dati ricevuti
		try{
			matricola = datiRicevuti.getString("matricola_agente");
			codice_agente = datiRicevuti.getString("codice_agente");
			imei = datiRicevuti.getString("IMEI");
			numeroVerbale = datiRicevuti.getString("nverbale");
			if(numeroVerbale == null || numeroVerbale.equals("")){
				numeroVerbale = VerbaliManager.getNumeroVerbale();
			}
			notifica = creaOggettoNotifica(datiRicevuti,numeroVerbale);
			
		}catch(Exception e) {
			errore = true;
			try{
		      	jsonToReturn.put("codice_errore",Costanti.PARSING_DATA_ERROR);
		      	jsonToReturn.put("info","Errore nell'elaborazione dell'oggetto JSON ricevuto: "+e.getMessage());
			}catch(JSONException je){}
			
			logger.error("Errore nella elaborazione dell'oggetto JSON ricevuto: "+e.getMessage());
		}
		if(!errore){
			//MEMORIZZAZIONE NEL DB DELLA NUOVA NOTIFICA
			dBmanager = DBManager.getDBManager();
			if((con = dBmanager.connect())!=null){
				try{
					inizioDB = System.currentTimeMillis();//codice per il calcolo ts
					esito = dBmanager.storeNotifica(con,notifica,matricola,codice_agente,imei);
					fineDB = System.currentTimeMillis();//codice per il calcolo ts
				}		
				catch(SQLException se) {
					errore = true;
					try{
				      	jsonToReturn.put("codice_errore",Costanti.SQL_ERROR);
				      	jsonToReturn.put("info","Errore nell'esecuzione della query SQL: "+se.getMessage());
					}catch(JSONException je){}
					
					logger.error("Errore nell'esecuzione della query SQL: "+se.getMessage());
				}
				catch(Exception ex){
					errore = true;
					try{
				      	jsonToReturn.put("codice_errore",Costanti.GENERIC_ERROR);
				      	jsonToReturn.put("info","Errore: "+ex.getMessage());
					}catch(JSONException je){}
					
					logger.error("Errore: "+ex.getMessage());
				}
				finally{
					if(dBmanager != null)	dBmanager.disconnect(con);
				}
	
			}
			else{
				errore = true;
		      	try{
		      	jsonToReturn.put("codice_errore",Costanti.DB_CONNECTION_ERROR);
		      	jsonToReturn.put("info","Errore nella connessione al DB server");
		      	}catch(JSONException e){}
		      	
		      	logger.error("Errore nella connessione al DB");
			}
	
			if(!esito.equals("Successo") && !errore){
				errore = true;
				try{
			      	jsonToReturn.put("esito_operazione", HttpServletResponse.SC_UNAUTHORIZED);
			      	if(esito.equals("Dispositivo non autorizzato"))
			      		 jsonToReturn.put("codice_errore",Costanti.UNKNOWN_DEVICE);
			      	else jsonToReturn.put("codice_errore",Costanti.UNKNOWN_AGENT);
			      	jsonToReturn.put("info","Errore: "+esito);
				}catch(JSONException je){}
				logger.info("Operazione non valida: "+esito);			
			}
			if(esito.equals("Successo")&& !errore){
				 //
				 //codice per il calcolo tempo esecuzione
				 //	
				fine = System.currentTimeMillis();
				long tsBE = fineDB - inizioDB;
				long tsFE = fine - inizio - tsBE;
				//////
				try{
			      	jsonToReturn.put("esito_operazione", HttpServletResponse.SC_OK);
			      	jsonToReturn.put("numero_verbale", numeroVerbale);
			      	jsonToReturn.put("tsFE",tsFE);
			      	jsonToReturn.put("tsBE",tsBE);
				}catch(JSONException je){}
				
				logger.info("La Notifica con numero verbale "+numeroVerbale+" e' stata aggiunta correttamente");
			}
		}
		return jsonToReturn;

	}
	
	
	@POST   @Path("/cancella")
	@Produces(MediaType.APPLICATION_JSON)
	@Consumes(MediaType.APPLICATION_JSON)
	public JSONObject cancellaNotifica(JSONObject datiRicevuti){
		// 
		// codice per il calcolo tempo esecuzione
		//			
		long inizio = System.currentTimeMillis();
		long fine = 0;
		long inizioDB = 0;
		long fineDB = 0;
						
      	JSONObject jsonToReturn = new JSONObject();
      	DBManager dBmanager = null;
      	Connection con = null;
      	boolean errore = false;
      	String esito = "";
      	String numeroVerbale = "";  
      	String matricola = "";
		String codice_agente = "";
		String imei = "";    	

      	//inizializzo i campi dell'oggetto JSON di risposta
      	try{
			jsonToReturn.put("esito_operazione", HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
			jsonToReturn.put("codice_errore","");
			jsonToReturn.put("info","");
			jsonToReturn.put("numero_verbale", "");
			jsonToReturn.put("tsFE",-1);
			jsonToReturn.put("tsBE",-1);
      		
      	}catch(JSONException je){}
      	
	    //parsing dei dati ricevuti
		try{
			matricola = datiRicevuti.getString("matricola_agente");
			codice_agente = datiRicevuti.getString("codice_agente");
			imei = datiRicevuti.getString("IMEI");
			numeroVerbale = datiRicevuti.getString("nverbale");
			
		}catch(JSONException e) {
			errore = true;
			try{
		      	jsonToReturn.put("codice_errore",Costanti.PARSING_DATA_ERROR);
		      	jsonToReturn.put("info","Errore nell'elaborazione dell'oggetto JSON ricevuto: "+e.getMessage());
			}catch(JSONException je){}
			
			logger.error("Errore nella elaborazione dell'oggetto JSON ricevuto: "+e.getMessage());
		}
		logger.info("Ricevuta la richiesta di cancellazione Notifica con numero di verbale "+(numeroVerbale!=null?numeroVerbale:""));
		if(!errore){	
			//AGGIORNAMENTO NEL DB DELLA NOTIFICA
			dBmanager = DBManager.getDBManager();
			if((con = dBmanager.connect())!=null){
				try{
					inizioDB = System.currentTimeMillis();//codice per il calcolo ts
					esito = dBmanager.deleteNotifica(con,numeroVerbale,matricola,codice_agente,imei);
					fineDB = System.currentTimeMillis();//codice per il calcolo ts
				}	
				catch(SQLException se) {
					errore = true;
					try{
				      	jsonToReturn.put("codice_errore",Costanti.SQL_ERROR);
				      	jsonToReturn.put("info","Errore nell'esecuzione della query SQL: "+se.getMessage());
					}catch(JSONException je){}
					logger.error("Errore nell'esecuzione della query SQL: "+se.getMessage());
				}
				catch(Exception ex){
					errore = true;
					try{
				      	jsonToReturn.put("codice_errore",Costanti.GENERIC_ERROR);
				      	jsonToReturn.put("info","Errore: "+ex.getMessage());
					}catch(JSONException je){}
					logger.error("Errore: "+ex.getMessage());
					
				}finally{
					if(dBmanager != null)	dBmanager.disconnect(con);
				}
			}
			else{
				errore = true;
				try{
			      	jsonToReturn.put("codice_errore",Costanti.DB_CONNECTION_ERROR);
			      	jsonToReturn.put("info","Errore nella connessione al DB server");
				}catch(JSONException e){}
		      	logger.error("Errore nella connessione al DB");
			}

			if(!esito.equals("Successo") && !errore){
				errore = true;
				try{
			      	jsonToReturn.put("esito_operazione", HttpServletResponse.SC_UNAUTHORIZED);
			      	if(esito.equals("Dispositivo non autorizzato"))	 jsonToReturn.put("codice_errore",Costanti.UNKNOWN_DEVICE);
			      	else jsonToReturn.put("codice_errore",Costanti.UNKNOWN_AGENT);
			      	jsonToReturn.put("info","Errore: "+esito);
				}catch(JSONException je){}
				
				logger.error("Errore: "+esito);			
			}
			if(esito.equals("Successo") && !errore){
				// 
				//codice per il calcolo tempo esecuzione
				//
				fine = System.currentTimeMillis();
				long tsBE = fineDB - inizioDB;
				long tsFE = fine - inizio - tsBE;
				try{
			      	jsonToReturn.put("esito_operazione", HttpServletResponse.SC_OK);
			      	jsonToReturn.put("numero_verbale", numeroVerbale);
			      	jsonToReturn.put("tsFE",tsFE);
			      	jsonToReturn.put("tsBE",tsBE);
				}catch(JSONException je){}
			
				logger.info("La notifica con numero verbale "+numeroVerbale+" e' stata cancellata correttamente");
			}
		}
		return jsonToReturn;

	}
	

	

}
